#!/usr/bin/env python
#
# Copyright J.H
#

#
# Save (add if no id given, otherwise update)
# /save?subject=xx&category=xx&amount=nn&date=mm/dd/yyyy&currency=xxx
#
# list receipts
# /list?n=xx&s=xx&lp=nn&gp=nn&ld=mm/dd/yyyy&gd=mm/dd/yyyy
#
# list category
# /category
#
# list subject
# /subject
#
from spending import Spending
from spending import Category
import demjson

from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp import util
from google.appengine.ext.webapp import template
from google.appengine.api import users

import os
import sys

from datetime import datetime

def login_asserted(handler_method):
  # A decorator to require that a user be logged in to access a handler.
  # This is inspired by google.appengine.webapp.util.login_required.
  # Instead of redirect, this method write an error message in order to support
  # post() method. Also a global user object is declared to facilitate the
  # handler method to access the current user object.
  #
  # To use it, decorate your post() method like this:
  #
  #   @login_asserted
  #   def post(self):
  #     self.response.out.write('Hello, ' + user.nickname())
  def check_login(self, *args):
    global user
    user = users.get_current_user()
    if not user:
      result={
        'success': False,
        'msg': 'User not logged in.'
      }
      self.response.out.write(demjson.encode(result))
      return
    else:
      handler_method(self, *args)
  return check_login

class SaveHandler(webapp.RequestHandler):
  @login_asserted
  def post(self):
    try:
      id=self.request.get("id")
      category=self.request.get("category")
      if not id:
        # create receipt
        spending=Spending(
          subject=self.request.get("subject"),
          category=category,
          currency=self.request.get("currency"),
          amount=float(self.request.get("amount")),
          date=datetime.strptime(self.request.get("date"),"%Y-%m-%d"))
        msg = 'New receipt saved'
      else:
        # update the give receipt
        spending=Spending.get_by_id(int(id))
        spending.subject=self.request.get("subject")
        spending.category=category
        spending.currency=self.request.get("currency")
        spending.amount=float(self.request.get("amount"))
        spending.date=datetime.strptime(self.request.get("date"),"%Y-%m-%d")
        msg = 'Receipt updated'
      spending.put()

      # create category if not exist
      catetory=Category.get_or_insert(key_name=category, name=category)

      # Return result in json
      result={
        'success': True,
        'msg': msg
      }
    except: 
      result={
        'success': False,
        'msg': str(sys.exc_info()[0]) + 'Input error'
      }
    self.response.out.write(demjson.encode(result))

class DelHandler(webapp.RequestHandler):
  @login_asserted
  def post(self):
    id=self.request.get("id")
    record=Spending.get_by_id(int(id))
    if record:
      record.delete()
      result={
        'success': True
      }
    else:
      result={
        'success': False,
        'msg': 'Non-existing record'
      }
    self.response.out.write(demjson.encode(result))

class CategoryHandler(webapp.RequestHandler):
  @login_asserted
  def get(self):
    query=Category.all()
    category_result={
      'success': True,
      'count': query.count(),
      'resultSet': [{'name':x.name} for x in query]
    }
    self.response.out.write(demjson.encode(category_result))

class SubjectHandler(webapp.RequestHandler):
  @login_asserted
  def get(self):
    query=Spending.all()
    #get distinct subjects
    result_set=set()
    for t in query:
      result_set.add(t.subject)
    subject_result={
      'success': True,
      'count': len(result_set),
      'resultSet': [{'name':x} for x in result_set]
    }
    self.response.out.write(demjson.encode(subject_result))

class ListHandler(webapp.RequestHandler):
  @login_asserted
  def get(self):
    where=""
    if self.request.get('startdate'):
      where+=(" AND date >= DATE('%s') " % self.request.get('startdate'))
    if self.request.get('enddate'):
      where+=(" AND date <= DATE('%s') " % self.request.get('enddate'))
    if self.request.get('category'):
      where+=(" AND category = '%s' " % self.request.get('category'))
    if self.request.get('subject'):
      where+=(" AND subject = '%s' " % self.request.get('subject'))

    query=db.GqlQuery('SELECT * FROM Spending '+
                      ' WHERE owner = :1 '+
                      where+
                      ' ORDER BY date DESC ',
                      user)
    #TODO:make this limit from get parameter
    receipts=query.fetch(int(self.request.get('count', default_value=32)))
    subtotal=0.0
    result_set=[]
    for receipt in receipts:
      subtotal+=receipt.amount
      result_set.append({
        'Id': receipt.key().id(),
        'Subject': receipt.subject, 
        'Category': receipt.category,
        'Amount': receipt.amount,
        'Currency': receipt.currency,
        'Date': receipt.date.strftime("%Y-%m-%d")})
    list_result={
      'success': True,
      'count': len(receipts),
      'subtotal': subtotal,
      'resultSet': result_set
    }

    if self.request.get("a")=='html':
      template_values={
        'results':list_result['resultSet']
      }
      path=os.path.join(os.path.dirname(__file__), 'list.htm')
      self.response.out.write(template.render(path, template_values))
    else:
      self.response.out.write(demjson.encode(list_result))

def main():
  application=webapp.WSGIApplication([('/list', ListHandler), ('/category', CategoryHandler), ('/subject', SubjectHandler), ('/save', SaveHandler), ('/del', DelHandler)],
                                     debug=True)
  util.run_wsgi_app(application)

if __name__ == '__main__':
  main()
